import json

import requests
from langchain.agents import ConversationalAgent, AgentExecutor
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import PromptTemplate
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

from langchain_rag.rag.hybrid_search import quchong


@tool(
    description="用于查询指定城市的天气。参数:city(必填,城市名称,示例:北京,苏州,上海),返回值:实时温度、湿度、天气状况、风向风力。用户问城市天气的时候必须调用这个工具,不可编造数据")
def WeatherTool(city: str) -> str:
    """
      https://www.juhe.cn/docs/api/id/73
      """

    try:

        # 1213-根据城市查询天气 - 代码参考（根据实际业务情况修改）

        # 基本参数配置
        apiUrl = 'http://apis.juhe.cn/simpleWeather/query'  # 接口请求URL
        apiKey = '89d99d8a8f8f20938ebfb99911c63367'  # 在个人中心->我的数据,接口名称上方查看

        # 接口请求入参配置
        requestParams = {
            'key': apiKey,
            'city': json.loads(city).get("city"),
        }

        print("requestParams:", requestParams)
        # 发起接口网络请求
        response = requests.get(apiUrl, params=requestParams)

        # 解析响应结果
        if response.status_code == 200:
            responseResult = response.json()
            # 网络请求成功。可依据业务逻辑和接口文档说明自行处理。
            print(responseResult)
            temperature = responseResult.get("result").get("realtime").get("temperature")
            humidity = responseResult.get("result").get("realtime").get("humidity")
            direct = responseResult.get("result").get("realtime").get("direct")
            power = responseResult.get("result").get("realtime").get("power")
            aqi = responseResult.get("result").get("realtime").get("aqi")
            res = f"""
            城市:{city}
            温度：{temperature}，
            湿度：{humidity}，
            空气质量指数：{aqi}
            风向：{direct}，
            风力：{power}
            """
            return res

        else:
            # 网络异常等因素，解析结果异常。可依据业务逻辑自行处理。
            print('请求异常')
            return "获取天气数据失败"
    except Exception as e:
        return f"获取天气数据失败:{str(e)}"


@tool(
    description="用于计算加减乘除运算.参数:expression(必填,数学表达式,示例: 2+4,10-2,3*6,10/2,2+3*7),返回值:计算结果.仅处理数字和+、-、*、/")
def CalculatorTool(expression: str) -> str:
    res = eval(expression)
    return f"计算结果:{expression}={res}"


@tool(
    description="用于查询公司知识库中的答案。参数:question(必填,问题,示例:中国有多少个民族,中国有多少个省级行政区),返回值:答案。用户问公司相关问题时必须调用这个工具,不可编造数据")
def RAGTool(question: str) -> str:
    rag_data = {
        "阅兵展示的武器": "阅兵展示的武器有东风-17、东风-41、东风-50、东风-21D、东风-31A、东风-41A、东风-41B、东风-41C、东风-41D、东风-41E、东风-41F、东风-41G、东风-41H、东风-41J、东风-41K、东风-41L、东风-41M、东风-41N、东风-41O、东风-41P、东风-41Q、东风-41R、东风-41S、东风-41T、东风-41U、东风-41V、东风-41W、东风-41X、东风-41Y、东风-41Z、东风-41AA、东风-41AB、东风-41AC、东风-41AD、东风-41AE",
        "中国的领土面积": "中国的领土面积960万平方公里",
        "中国有多少个民族": "中国有56个民族",
        "中国有多少个省级行政区": "中国有34个省级行政区"
    }

    for key, value in rag_data.items():
        if key in question:
            return value
    return f"在知识库中没有找到[{question}]答案"


@tool(
    description="用于查询保险知识库中的答案。参数:question(必填,问题,示例:如何报销住院费用,人身保险是怎么定义的),返回值:答案。用户问保险相关问题时必须调用这个工具,不可编造数据")
def baoxianTool(question: str) -> list:
    data_list = quchong(question)
    if data_list:
        return data_list
    else:
        return []


tools = [WeatherTool, CalculatorTool, RAGTool,baoxianTool]

llm = ChatOpenAI(
    model_name="qwen-plus",
    api_key="sk-6434b554122c4b049ceb805d703f695b",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# 核心:创建会话记忆
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True,  # 返回Message对象，方便Agent理解

)

prompt_template = """
你是一个帮助用户解决问题的智能助手，你拥有以下工具:
{tools}

使用规则:
1:先理解问题,结合对话历史{chat_history}:无需工具则直接回答,需要工具则调用工具(根据工具的描述匹配)
2:调用工具必须用格式：```json{{"name":"工具名","parameters":{{"参数名":"参数值"}}}}```（参数需齐全）；
3:拿到工具结果后, 判断是否继续调用工具, 如果需要继续调用工具,则调用工具,否则整理,返回结果;


用户的问题:{input}
"""

propmt = PromptTemplate(
    input_variables=["tools", "chat_history", "input"],
    template=prompt_template
)

agent = ConversationalAgent.from_llm_and_tools(
    llm=llm,
    tools=tools,
    prompt=propmt,
    verbose=True,

)

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    handle_parsing_errors=True,
    max_iterations=5,
    memory=memory,  # 关键:把记忆绑定到执行器

)

if __name__ == '__main__':
    res = agent_executor.invoke({"input":"如何报销住院费用"})
    print("回答：", res["output"], "\n")
    # print("=======第一轮对话==========")
    # print("对话历史:", memory.buffer)
    # res1 = agent_executor.invoke({"input": "郑州市今天的天气怎么样？"})
    # print("回答：", res1["output"], "\n")
    #
    # print("=======第二轮对话==========")
    # print("对话历史:", memory.buffer)
    # res2 = agent_executor.invoke({"input": "那适合穿什么样的衣服?"})
    # print("回答：", res2["output"], "\n")
    #
    # print("=======第三轮对话==========")
    # print("对话历史:", memory.buffer)
    # res3 = agent_executor.invoke({"input": "如果买一件🩲(199),和一件背心(199),一共多少钱?"})
    # print("回答：", res3["output"], "\n")
